package utils

import (
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"strconv"
	"strings"

	"math/rand"

	"golang.org/x/crypto/pbkdf2"
)

const Iterations int = 390000
const KeyLen int = sha256.Size

var letters = []rune("123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

// 输入字符长度，生成随机字符串
func randStr(n int) string {

	b := make([]rune, n)

	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}

// storedHash是查询出来的用户hash, password是输入的密码，进行比较输入是否正确
func GeneratePasswordHash(password string) (string, error) {
	salt := randStr(22)
	hash := pbkdf2.Key([]byte(password), []byte(salt), Iterations, sha256.Size, sha256.New)
	hashBase64 := base64.StdEncoding.EncodeToString(hash)
	result := fmt.Sprintf("pbkdf2_sha256$%d$%s$%s", Iterations, salt, hashBase64)
	return result, nil
}

// 验证密码是否正确(兼容了django的默认加密)
func VerifyPassword(storedHash string, password string) (bool, error) {
	// 分解 hash 字符串
	parts := strings.Split(storedHash, "$")
	if len(parts) != 4 {
		return false, fmt.Errorf("invalid hash format")
	}

	// 提取迭代次数、盐值、哈希值
	iterations, err := strconv.Atoi(parts[1])
	if err != nil {
		return false, fmt.Errorf("invalid iteration count")
	}

	salt := []byte(parts[2])

	storedHashBytes, err := base64.StdEncoding.DecodeString(parts[3])
	if err != nil {
		return false, fmt.Errorf("invalid hash encoding")
	}

	// 使用 PBKDF2 计算哈希值
	computedHash := pbkdf2.Key([]byte(password), salt, iterations, sha256.Size, sha256.New)

	computedHashStr := string(computedHash)
	storedHashStr := string(storedHashBytes)

	// 比较计算出的哈希与存储的哈希
	if computedHashStr == storedHashStr {
		return true, nil
	}

	return false, nil
}

// func Test() {
// 	// hash := `pbkdf2_sha256\$390000$iI5iVFnZMDVmL2L7Bw5nL0$f7O8ArVr1XJoaK/Uwop43GHH1iPy22GygkeWqU2nxU0=`
// 	// hash := `pbkdf2_sha256$390000$SDFD21342DSsdf$VCEqR0t7zF0Eyw7s3DiFrfivcT/c4ln9Ov3QjvcwZis=`
// 	hash := `pbkdf2_sha256$390000$ZmG3cbHttPh15bJT$PpmdJMB9xkt30xkKsZIU7VpIhok6NT+9K2Z/91LjHrc=`
// 	password := "chenhaifeng"

// 	valid, err := verifyPassword(hash, password)
// 	if err != nil {
// 		fmt.Println("Error:", err)
// 	} else if valid {
// 		fmt.Println("Password is valid!")
// 		pwdHash, _ := generatePasswordHash(password)
// 		fmt.Println(pwdHash)
// 	} else {
// 		fmt.Println("Invalid password")
// 	}
// }
